#include"stdio.h"
#include"unistd.h"
#include"string.h"
#include"ctype.h"

//字符统计函数
void CharCount(FILE *pt)
{
	int sum = -1;//linux系统中会在文本文件末尾加入$不显示，空文件不会。
	int re_c = 0;//fgetc函数返回一个由字符类型转换而来的int值。
	re_c = fgetc(pt);
	while(1)
	{
		sum++;
		re_c = fgetc(pt);
		if(feof(pt))
		{
			printf("have read at the end 0f file\n");
			break;
		}
		
	}
	//重置位置指针至开头
	rewind(pt);
	printf("文件中字符总数为%d\n",sum);
}
//单词统计函数
void WordCount(FILE *pt)
{
	int sum = 0;
	char flag;

	flag = fgetc(pt);
	while(1)
	{
		//从单词头读到单词末
		if(isalpha(flag))
		{
			while(isalpha(flag))
			{
				flag = fgetc(pt);
			}
			sum++;
		}
		
		if(feof(pt))//如果读到文件末尾或读错（概率很小）
        	{
                	printf("have read at the end of file\n");
                	break;
        	}
		flag = fgetc(pt);
	}
	printf("文件中单词总数为%d\n",sum);
	//重置位置指针至开头
	rewind(pt);
}
//句子数统计函数
void LineCount(FILE *pt)
{

    int sum = 0;
    int re_c =0;

    re_c = fgetc(pt);
    while(1)
    {
        if(re_c == 33 || re_c == 63 || re_c == 46 || re_c == 59)//各种句子结束标点符号对应的十进制值
        {
            sum++;
        }
        re_c=fgetc(pt);
	if(feof(pt))
	{
		printf("have read at the end of file\n");
		break;
	}
    }
    printf("文件中句子总数为%d\n\n\n",sum);
    //重置位置指针至开头
    rewind(pt);
}
//计算各类行数
void Vary_Line_Count(FILE *pt)
{
	printf("当注释行和代码行共存时，同时计入注释行和代码行的总数\n\n\n");
	int Total_Line_Sum = 0;
	int EmptyLine = 0;
	int ExpLine = 0;
	char flag;
	int offset = 0;
       	char buff[80];
//统计总行数
	flag = fgetc(pt);	
	while(1)
	{
		if(flag == '\n' ||  flag == '\0')
		{
			Total_Line_Sum++;
		}
		if(feof(pt))
		{
			printf("have read at the end of file\n");
			break;
		}
		flag = fgetc(pt);
	}
	rewind(pt);

	//统计注释行数和空行数
	fgets(buff,sizeof(buff),pt);//读入文件中指定大小的一行的数据进buff
	int s = -1;
	while(1)
	{
		s++;
		if(buff[0] == '\0' || buff[0] == '\n')
		{
			EmptyLine++;//不包括任何字符
		}

		int i = 0;
		while(buff[i] != '\n' && buff[i] != '\0')
		{
			if(buff[i] == '/')
			{
				if(buff[i + 1] == '/')
				{
					for(int j = 0;j < i;j++)
                        		{
                                		if(isalpha(buff[j]))
                                		{
							if(s != Total_Line_Sum)
							{
                                        		  	offset++;
                                        		 	break;
							}
							break;
                                		}
                        		}

					if(s == Total_Line_Sum)
					{	
						ExpLine--;
					}
				ExpLine++;
				break;
				}
				break;
			}
			i++;
		}

		if(feof(pt))
		{
			 printf("have read at the end of file\n");
			 break;
		}

		fgets(buff,sizeof(buff),pt);
	}
	rewind(pt);
	printf("%d",s);
	printf("文件中总行数为%d\n",Total_Line_Sum);
	printf("文件中总空行数为%d\n文件中注释行数为%d\n文件中代码行数为%d\n",EmptyLine,ExpLine,Total_Line_Sum - ExpLine - EmptyLine + offset);
	


}

int main(int argc,char *argv[])
{
	printf("-------------------------------------------------------------------------------------------------------------------\n");
	printf("该命令提供的参数有 -c -w -l -cw -cl -wl -cwl,-v,-cwlv;\n若没有显示结果，请检查是否参数出错，或源文件格式有误\n\n\n");
	printf("该命令统计单词个数包括注释，句子判定标准我自认为是以'.','!','?'为标记统计\n\n\n");
	//打开文件
	FILE *rd_pt;//源文件指针
	rd_pt = fopen(argv[2],"r");

	if(rd_pt == NULL)
	{
		printf("open %s file failed\n\n\n",argv[2]);
	}
	printf("open %s file success\n\n\n",argv[2]);

	if(strcmp(argv[1],"-c") == 0)
	{
		CharCount(rd_pt);		
	}
	if(strcmp(argv[1],"-l")==0)
	{
		LineCount(rd_pt);
	}
	if(strcmp(argv[1],"-w")==0)
	{
		WordCount(rd_pt);

	}
	if(strcmp(argv[1],"-cl")==0)
        {
		CharCount(rd_pt);
		LineCount(rd_pt);
        }
        if(strcmp(argv[1],"-cw")==0)
	{
		CharCount(rd_pt);
		WordCount(rd_pt);

        }
        if(strcmp(argv[1],"-wl")==0)
        {
		LineCount(rd_pt);
		WordCount(rd_pt);

        }
        if(strcmp(argv[1],"-cwl")==0)
        {       
		CharCount(rd_pt);
		WordCount(rd_pt);
		LineCount(rd_pt);
        }
	if(strcmp(argv[1],"-v")==0)
	{
	Vary_Line_Count(rd_pt);
	}
	if(strcmp(argv[1],"-cwlv")==0)
        {
	CharCount(rd_pt);
        WordCount(rd_pt);
        LineCount(rd_pt);
        Vary_Line_Count(rd_pt);
        }

	//关闭文件
	fclose(rd_pt);
	printf("--------------------------------------------------------------------------------------------------\n");
	return 0;
}
